#include <iostream>
#include <exception>
using namespace std;

class MyException1: public exception {
    public:
        MyException1(char const *msg): _msg(msg){
           cout << "Calling MyException1::MyException1(msg)!" << endl;
        }
        MyException1(MyException1 const &obj) {
           cout << "Calling MyException1::MyException1(&obj)!" << endl;
        }
        ~MyException1() throw() {
           cout << "Calling MyException1::~MyException1()!" << endl;
        }
        char const *what() const throw() {
            return _msg.c_str();
        }
    private:
        string _msg;
};


class MyException2: public MyException1 {
    public:
        MyException2(char const *msg): MyException1(msg) {
            cout << "Calling MyException2::MyException2(msg)" << endl;
        }
        MyException2(MyException2 const &obj): MyException1(obj.what()){
            cout << "Calling MyException2::MyException2(&obj)" << endl;
        }
        ~MyException2() throw() {
            cout << "Calling MyException2::~MyException2()" << endl;
        }
    
};


void fun(int n) throw(int, MyException1, MyException2) {
    switch(n) {
    case 1:
        throw 1;
        break;
    case 2:
        throw MyException1("Test MyException1");
        break;
    case 3:
        throw MyException2("Test MyException2");
        break;
    default:
        cout << "Do nothing!" << endl;
        break;
    }
}

void fun2() throw() {};
void fun3() throw() {};

int main(void) {
    try {
        fun(3);
    } catch(int e) {
        cout << "catch int ..." << endl;
        cout << "n=" << e << endl;
    } catch(MyException1 &e)  {
        cout << "catch MyException1" << endl;
        cout << e.what() << endl;
    } catch(MyException2 e) {
        cout << "catch MyException2" << endl;
        cout << e.what() << endl;
    }
    return 0;
}
